/***************
Copyright (C) 2010 by James Nutaro

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

Bugs, comments, and questions can be sent to nutaro@gmail.com
***************/
package adevs;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Collection;

/**
 * This is a very simple digraph model for connecting single input/single output
 * systems. Output events generated by a component model are sent to all
 * connected models. This is, in fact, a Java implementation of the SimpleDigraph
 * class that appears in the C++ simulation package.
 */
public class SimpleDigraph extends Network
{
	/**
	 * Construct a network without components.
	 */
	public SimpleDigraph()
	{
		super();
		graph = new HashMap<Devs,ArrayList<Devs> >();
	}
	/**
	 * Add a model to the network.
	 * @param model The DEVS model that will be a component of the network
	 */
	public void add(Devs model)
	{
		if (!graph.containsKey(model))
		{
			graph.put(model,new ArrayList<Devs>());
		}
	}
	/**
	 * Couple the source model to the destination model.
	 */
	public void couple(Devs src, Devs dst)
	{
		add(src);
		add(dst);
		graph.get(src).add(dst);
	}
	/**
	 * Puts the network's set of components into c.
	 * @param c A Collection to which will be added the model's components
	 */
	public void getComponents(Collection<Devs> c)
	{
		Collection<Devs> components = graph.keySet();
		for (Devs model: components)
		{
			if (model != this) c.add(model);
		}
	}
	/**
	 * Route an event according to the network's couplings.
	 * @see Network
	 */
	public void route(Object x, Devs model, Collection<Event> r)
	{
		// Find the list of target models and ports
		ArrayList<Devs> targets = graph.get(model);
		// If no target, just return
		if (targets == null) return;
		// Otherwise, add the targets to the event bag
		for (Devs dst: targets)
		{
			r.add(new Event(dst,x));
		}
	}

	private HashMap<Devs,ArrayList<Devs> > graph;
};
